package com.dingwen.treasure.websocket.client.handler;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.socket.*;
import org.springframework.web.socket.client.WebSocketConnectionManager;

import javax.annotation.Resource;
import java.nio.ByteBuffer;

/**
 * 　TreasureWebSocketClientHandler
 * 　@author dingwen
 * 　@date 2022/8/31
 */
@Component("treasureWebSocketHandler")
@Slf4j
public class TreasureWebSocketHandler implements WebSocketHandler {


    /**
     * 重连次数
     */
    private Integer reconnectCount = 0;


    @Resource(name = "webSocketConnectionManager")
    @Lazy
    private WebSocketConnectionManager webSocketConnectionManager;
    /**
     * 当前客户端连接到服务端端的会话
     */
    private WebSocketSession webSocketSession;

    /**
     * 连接建立之后触发端回调
     *
     * @param webSocketSession web socket会话
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) {
        log.info("连接建立之后触发端回调");
        this.webSocketSession = webSocketSession;
    }

    /**
     * 收到消息时触发的回调
     *
     * @param webSocketSession web socket会话
     * @param webSocketMessage 网络套接字信息
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) {
        log.info("webSocketMessage:{}", webSocketMessage);
        log.info("收到消息时触发的回调");
    }

    /**
     * 传输消息出错时触发调回调
     *
     * @param webSocketSession web socket会话
     * @param throwable        throwable
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) {
        log.info("传输消息出错时触发调回调");
    }

    /**
     * 断开连接后触发的回调
     *
     * @param webSocketSession web socket会话
     * @param closeStatus      关闭状态
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) {
        log.info("断开连接后触发的回调");
    }


    /**
     * 发送消息
     *
     * @param message 消息
     */
    @SneakyThrows(Throwable.class)
    public void sendMessage(String message) {
        if (isConnected()) {
            webSocketSession.sendMessage(new TextMessage(message));
            log.info("客户端主动给服务端发送消息：{}", message);
        }
    }


    /**
     * 判断连接是否存在
     *
     * @return boolean
     */
    public boolean isConnected() {
        return !(ObjectUtils.isEmpty(webSocketSession) || !webSocketSession.isOpen());
    }


    /**
     * 是否支持分片
     *
     * @return boolean
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    /**
     * 每30秒发送一个心跳,检测断开后重连
     */
    @Scheduled(cron = "0 */1 * * * ?")
    @SneakyThrows(Throwable.class)
    public void heartBeat() {
        log.info("每30秒发送一个心跳,检测断开后重连");
        if (isConnected()) {
            this.webSocketSession.sendMessage(new PongMessage(ByteBuffer.wrap("1".getBytes())));
        } else {
            this.reconnectCount++;
            log.info("客户端断开连接，心跳监测开始，进行重连");
            // 重连
            webSocketConnectionManager.startInternal();
        }
    }
}
